package com.acme.bankapp.domain.bank;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.acme.bankapp.domain.exceptions.BankException;


public class Client implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private Gender gender;
	private String name;
	private int num;
	private Map <Integer, AbstractAccount> accounts;
	transient private Set <Integer> accountsID;
	private StringBuffer info = new StringBuffer();
		
	public Client(AbstractAccount account, double amount, String name, Gender g) {
		accounts = new HashMap <Integer, AbstractAccount> ();
		num = 1;		
		account.deposit(amount);
		accounts.put(new Integer(account.getID()), account);
		accountsID = accounts.keySet();
		this.name = name;
		gender = g;
		info.append("\n" + g.getGender() + name + " has " + num + " account(s):\n");
		info.append(account.toString() + "\n");
		
	}
	
	public Client(AbstractAccount account, double amount) {
		this(account, amount, null, Gender.MALE);
	}
	
	public Client() {
		this(null, 0, null, Gender.MALE);
	}	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + getClientSalutation().hashCode();		
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Client)) {
			return false;
		}
		Client other = (Client) obj;

		if (!getClientSalutation().equals(other.getClientSalutation())) {			
			return false;
		}			
		return true;
	}
		
	@Override
	public String toString() {		
		return info.toString();
	}

	public String getClientSalutation() {
		return gender.getGender() + name;
	}
	
	public String getClientName() {
		return name;
	}	
	
	public Account getAccount (int id) throws BankException {
		if (!accounts.containsKey(id)) {			
			throw new BankException();
		}		
		return accounts.get(id);
	}
	
	public Map<Integer, AbstractAccount> getAccounts () {
			
		return Collections.unmodifiableMap(accounts);
	}
	
	public void addAcount (AbstractAccount account) {
		accounts.put(account.getID(), account);
		accountsID.add(account.getID());
		info.append(account.toString() +"\n");
	}

}
